package mas;

import java.util.Hashtable;

/** Class which represents a Portal Agent which is used to provide routing 
 * capability for Message objects
 * 
 * Advanced Java Programming - ICA 2 Middleware 
 * @author Carl Morphet, Matt Constable, Stephen Pammenter
 * Teesside University
 * Created: Mar 20, 2012
 */
public class Portal extends MetaAgent
{
    //TODO: Talk about possibilies of dynamic hash table in report, 
    
    /** The hash table which stores all the agent identifiers and references */
    protected Hashtable routingTable;
    
    /** The portals identifier */
    private String portalName;
    
    /** A local MetaAgent object used in the overridden msgHandler method*/
    private MetaAgent agent;
    
    /** A local Portal object used for message routing */
    private Portal portal;

    /** Constructor which calls the MetaAgent constructor and instantiates the
     * Portal agents instance variables 
     * 
     * @param name The portals identifier
     */
    public Portal(String name) 
    {
        super(name);
        portalName = name;
        routingTable= new Hashtable();
    }
    
    /** Accessor method which returns the portals identifier 
     * 
     * @return The portals identifier 
     */
    public String getPortalName()
    {
        return portalName;
    }
    
    /** Method which registers the agent with the portal, ensures agents
     * cannot be registered multiple times
     * 
     * @param name The identifier of the agent to be registered
     * @param agent The agent object to be registered
     * @return true or false depending if the register was successful 
     */
    public boolean registerAgent(String name, MetaAgent agent)
    {
        if(routingTable.get(name) != null)
            return false;
        
        try
        {
            routingTable.put(name, agent);
            agent.setPortal(this);
        }
        catch (Exception ex)
        {
            System.err.println("Portal: " + ex.getMessage());
            return false;
        }
        finally
        {
            return true;
        }
    }
    
    /** Method which de-registers agents with the portal 
     * 
     * @param name The name of the agent to be removed from the routing table
     * @return true or false depending if the de-register was successful
     */
    public boolean deRegisterAgent(String name)
    {
        try
        {
            routingTable.remove(name);
        }
        catch(Exception ex)
        {
            System.err.println("Portal: " + ex.getMessage());
            return false;
        }
        finally
        {
            return true;
        }
    }
    
    /** An override of the MetaAgents msgHandler method which routes the message
     * to the correct agent, it checks if this portal is related to the intended
     * recipient, it if it it routes the message to it, else it checks through 
     * any other portals to see if they are linked to the recipient Agent and 
     * routes the message through their routing table
     * 
     * @param message The message to be routed 
     */
    @Override
    public void msgHandler(Message message)
    {
        String recipient = message.getRecipient();

        if(routingTable.containsKey(recipient))
        {
            agent = (MetaAgent) routingTable.get(recipient);
        }
        else
        {
            for(Object o :routingTable.values())
            {
                if(o instanceof Portal)
                {
                    portal = (Portal) o;

                    if(portal.routingTable.containsKey(recipient))
                    {
                        agent = (MetaAgent)portal.routingTable.get(recipient);
                    }
                }
            }
        }

        agent.msgHandler(message);
    }
}